export type Lazy<T> = () => T;



export type LazyConvert<T, S> = (x: Lazy<T>) => Lazy<S>;
export type LazyAggretate<T, S> = (elem: Lazy<T>) => (acc: Lazy<S>) => Lazy<S>;



// TODO: 
// type Number = number | null;
// type LazyNumber = Lazy<Number>;
export type LazyNumber = Lazy<number>;




export type List<T> = {
    head: Lazy<T>,
    tail: LazyList<T>
} | null;
export type LazyList<T> = Lazy<List<T>>;

// 将数组转化为 LazyList
export function toList<T>(xs: T[]): LazyList<T> {
    return () => {
        if (xs.length === 0) {
            return null;
        }
        return {
            head: () => xs[0],
            tail: toList(xs.slice(1))
        };
    }
}

export function printLazy<T>(x: Lazy<T>) {
    console.log(x())
}

// 打印 LazyList，一行一个元素
export function printList<T>(lxs: LazyList<T>) {
    let xs = lxs();
    while (xs !== null) {
        printLazy(xs.head)
        xs = xs.tail();
    }
}


export type Pair<T, S> = {
    a: Lazy<T>,
    b: Lazy<S>
} | null

export type LazyPair<T, S> = Lazy<Pair<T, S>>;

export const pair = <T, S>(x: Lazy<T>) => (y: Lazy<S>): LazyPair<T, S> => {
    return () => {
        return {
            a: x,
            b: y
        }
    }
}

export function printLazyPair<T, S>(lp: LazyPair<T, S>) {
    const p = lp();
    if (p === null) {
        console.log("invalid input for func `printLazyPair`")
        return;
    }
    console.log(`(${p.a()}, ${p.b()})`)
}

export function printLazyPairList<T, S>(lps: LazyList<Pair<T, S>>) {
    let ps = lps();
    while (ps !== null) {
        printLazyPair(ps.head)
        ps = ps.tail();
    }
}